/**
 * @file		moreConstParams.cpp
 * @description		This sample adds the const modifier to the equals
 *			function. This modifier tells the compiler that
 *			we are not going to modify the calling object. 
 *			In this sample the calling object is mtnBike.
 * @course		CSCI 123 Section 00000
 * @assignment 
 * @date		mm/dd/yyyy
 * @author		Brad Rippe (00000000) brippe@fullcoll.edu
 * @version		6.0
 */
#include <iostream>
#include <string>
using namespace std;

/**
 * This is the bike class. The public members and functions
 * are accessible to every. The private members and functions
 * are only accessible to the class. This example doesn't use
 * a constructor to create the Bike Object. In this case, C++
 * will provide one for us that does NOTHING.
 */ 
class Bike {
public:

	/**
	 * This is the default constructor. This constructor
	 * creates a Bike object without specifying any parameters
	 */
	Bike();

	/**
	 * Creates a Bike.
	 * @param aName  sets the bike's name
	 * @param aSize sets the bike's frame size
	 * @param aDiameter sets the bike's wheel diameter
	 */
	Bike(const string& aName, int aSize, double aDiameter);

	/**
	 * Gets the bike's name.
	 * @return the name of the bike
	 */
	string getName() const;

	/**
	 * Set the bike's name.
	 * @param aName the name to set the bike's name to.
	 */
	void setName(const string& aName);

	/**
	 * Gets the bike's name.
	 * @return the name of the bike
	 */
	int getSize() const;

	/**
	 * Set the bike's frame size.
	 * @param aSize the size to set the bike's frame to.
	 */
	void setSize(int aSize);

	/**
	 * Gets the bike's name.
	 * @return the name of the bike
	 */
	double getWheelDiameter() const;

	/**
	 * Set the bike's wheel diameter
	 * @param aDiameter the diameter to set the bike's diameter to.
	 */
	void setWheelDiameter(double aDiameter);

	/**
	 * Compares two bikes to see if their internal data is the 
	 * same. If so, we consider them to be the same bike.
	 * NOTICE the const modifier at the end of the function declaration
	 * and the function definition.
	 * @param aBike the bike to test this bike for equality
	 * @return true if the two bikes are equal, otherwise false
	 */
	bool equals(const Bike& aBike) const;

private:
	// this is a private function, only this class can access
	// a private function. Private functions are usually utility
	// functions for the class. They won't be accessed by others
	// therefore the documentation can be left out. We only want to
	// expose the api that others can use.
	bool validSize(int aSize);
	string mName;
	int mSize;
	double mWheelDiameter;
};

/**
 * @return zero if the application executes successfully
 */
int main() {

	Bike mtnBike;
	mtnBike.setName("Foes");		// users have to use accessors
	mtnBike.setSize(18);			// and mutators to get to the 
	mtnBike.setWheelDiameter(26.0);		// private data in the object

	Bike mtnBike2 = mtnBike;		// the assignment operator copies
						// all the members in one object to
						// another

	cout << "Is mtnBike1 equal to mtnBike2?\n";
	cout << "mtnBike.equals(mtnBike2) = ";
	if(mtnBike.equals(mtnBike2))
		cout << "true\n" << endl;
	else
		cout << "false\n" << endl;
	return 0;
}

// Default Constructor
Bike::Bike() : mName("Unknown Name"), mSize(10), mWheelDiameter(12.0) {
	/* empty */
}

Bike::Bike(const string& aName, int aSize, double aDiameter) :
			mName(aName), mSize(aSize), mWheelDiameter(aDiameter) {
	if(aName == "")
		mName = "Unknown Name";
	if(!validSize(aSize))
		mSize = 10;
	if(aDiameter <= 4)
		mWheelDiameter = 5.0;
}

// the const modifier tells the compiler were not going to 
// modify the calling object
string Bike::getName() const {
	return mName;
}

void Bike::setName(const string& aName) {
	mName = aName;
}

// the const modifier tells the compiler were not going to 
// modify the calling object
int Bike::getSize() const {
	return mSize;
}

void Bike::setSize(int aSize) {
	if(validSize(aSize))
		mSize = aSize;
	else
		mSize = 10;
}

// the const modifier tells the compiler were not going to 
// modify the calling object
double Bike::getWheelDiameter() const {
	return mWheelDiameter;
}

void Bike::setWheelDiameter(double aDiameter) {
	mWheelDiameter = aDiameter;
}

bool Bike::validSize(int aSize) {
	return (aSize >= 10);
}

// notice the const modifier at the end of the definition
// we can use the getName(), getSize, and getWheelDiameter
// because we used the const modifier in the declaration
// and definition of those functions. Without the const modifier
// in those functions, the compiler will complain. This is our
// guarantee that we won't change the data of the caller
bool Bike::equals(const Bike& aBike) const {
	/* can't use mName = "Some Value"; because of the
	   const on the end of the declaration/definition
	 */
	if(mName != aBike.getName() ||
		mSize != aBike.getSize() ||
		mWheelDiameter != aBike.getWheelDiameter()) {
			return false;
	}
	return true;
}

